﻿/*
____
 L|ypps Web controls for ASP.NET

Copyright (c) 2009 Alessandro Zifiglio, http://www.Typps.com
EMail: alessandro@Typps.com

This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/
namespace Typps
{
    using System;
    using System.Collections;
    using System.Collections.Generic;
    using System.Collections.Specialized;
    using System.ComponentModel;
    using System.ComponentModel.Design;
    using System.Configuration;
    using System.Data;
    using System.Drawing;
    using System.Drawing.Design;
    using System.Globalization;
    using System.IO;
    using System.Reflection;
    using System.Resources;
    using System.Text;
    using System.Threading;
    using System.Web;
    using System.Web.Hosting;
    using System.Web.Script.Serialization;
    using System.Web.Security;
    using System.Web.UI;
    using System.Web.UI.HtmlControls;
    using System.Web.UI.WebControls;
    using System.Web.UI.WebControls.WebParts;
    using System.Xml;

    [ToolboxBitmap(typeof(ResourceDummy), "Typps.Resources.Images.colorpicker.bmp")]
    [DefaultProperty("TargetControlImageUrl")]
    [Designer(typeof(Typps.ColorPickerDesigner))]
    [ToolboxData("<{0}:ColorPicker runat=\"server\"></{0}:ColorPicker>")]
    public class ColorPicker : ControlBase
    {
        #region Fields

        string _baseImageSkinFolder = "Typps.Resources.Skins.{0}.Images.Editor.{1}";
        private string[] _commonCssImageList = new string[] { "tristatebutton80x33.gif", "tristatebutton110x33.gif", "tristatebutton200x33.gif", "tristateclosebutton16x48.gif" };
        private ClientScriptManager _cs;
        string _cssKey = "Typps.ColorPicker";
        private UpdatePanelProgress _embeddedUpdatePanelProgress;
        string _keyFormat = "ColorPicker_{0}";
        private System.Web.UI.WebControls.Image _popperImage = null;
        string _rootImageSkinFolder = "Typps.Resources.Skins.{0}.Images.ColorPicker.{1}";
        string _rootSkinFolder = "Typps.Resources.Skins.{0}.{1}";
        string _rootTemplateSkinFolder = "Typps.Resources.Skins.{0}.Templates.{1}";
        string _styleSheetName = "Css.colorpicker.css";
        private string _webResponseData = string.Empty;

        #endregion Fields

        #region Constructors

        public ColorPicker()
            : base("div")
        {
        }

        #endregion Constructors

        #region Events

        //Invoke delegates registered with the Click event.
        public event ColorSelectionEventHandler ColorSelectionChanged;

        #endregion Events

        #region Properties

        [DefaultValue("Loading Color Palette designer ..."),
        NotifyParentProperty(true),
        RefreshProperties(RefreshProperties.Repaint)]
        public string ColorPickerDesignerLoadingMessage
        {
            get { return (ViewState["ColorPickerDesignerLoadingMessage"] == null) ? GetLocalizedText("DesignerLoadingMessage") : ViewState["ColorPickerDesignerLoadingMessage"].ToString(); }
            set { ViewState["ColorPickerDesignerLoadingMessage"] = value; }
        }

        public override ControlCollection Controls
        {
            get
            {
                this.EnsureChildControls();
                return base.Controls;
            }
        }

        [DefaultValue(typeof(DisplayMode), "Inline"),
        NotifyParentProperty(true),
        RefreshProperties(RefreshProperties.Repaint)]
        public DisplayMode Display
        {
            get
            {
                return (ViewState["Display"] == null) ?
                    DisplayMode.Inline : (DisplayMode)ViewState["Display"];
            }
            set
            {
                ViewState["Display"] = value;
            }
        }

        [PersistenceMode(PersistenceMode.InnerProperty),
        DesignerSerializationVisibility(DesignerSerializationVisibility.Content),
        NotifyParentProperty(true),
        RefreshProperties(RefreshProperties.Repaint)]
        public UpdatePanelProgress EmbeddedUpdatePanelProgress
        {
            get
            {
                if (_embeddedUpdatePanelProgress == null)
                    _embeddedUpdatePanelProgress = new UpdatePanelProgress();
                return _embeddedUpdatePanelProgress;
            }
        }

        /// <summary>
        /// Control is initialized manually by a call clientside via
        /// initializeRequest(). In order to do this, you need to use
        /// $find() first and then call the initializeRequest method on it.
        /// </summary>
        [DefaultValue(false),
        Category("Control will be initialized manually"),
        NotifyParentProperty(true),
        RefreshProperties(RefreshProperties.Repaint)]
        public bool ManuallyInitialize
        {
            get { return (ViewState["ManuallyInitialize"] == null) ? false : (bool)ViewState["ManuallyInitialize"]; }
            set { ViewState["ManuallyInitialize"] = value; }
        }

        [DefaultValue(""),
        Category("ClientSide Events"),
        NotifyParentProperty(true),
        RefreshProperties(RefreshProperties.Repaint)]
        public string OnClientBeginWebRequest
        {
            get { return (ViewState["OnClientBeginWebRequest"] == null) ? string.Empty : (string)ViewState["OnClientBeginWebRequest"]; }
            set { ViewState["OnClientBeginWebRequest"] = value; }
        }

        [DefaultValue(""),
        Category("ClientSide Events"),
        NotifyParentProperty(true),
        RefreshProperties(RefreshProperties.Repaint)]
        public string OnClientCancelButton
        {
            get { return (ViewState["OnClientCancelButton"] == null) ? string.Empty : (string)ViewState["OnClientCancelButton"]; }
            set { ViewState["OnClientCancelButton"] = value; }
        }

        [DefaultValue(""),
        Category("ClientSide Events"),
        NotifyParentProperty(true),
        RefreshProperties(RefreshProperties.Repaint)]
        public string OnClientEndWebRequest
        {
            get { return (ViewState["OnClientEndWebRequest"] == null) ? string.Empty : (string)ViewState["OnClientEndWebRequest"]; }
            set { ViewState["OnClientEndWebRequest"] = value; }
        }

        [DefaultValue(""),
        Category("ClientSide Events"),
        NotifyParentProperty(true),
        RefreshProperties(RefreshProperties.Repaint)]
        public string OnClientOkButton
        {
            get { return (ViewState["OnClientOkButton"] == null) ? string.Empty : (string)ViewState["OnClientOkButton"]; }
            set { ViewState["OnClientOkButton"] = value; }
        }

        [DefaultValue(""),
        Category("ClientSide Events"),
        NotifyParentProperty(true),
        RefreshProperties(RefreshProperties.Repaint)]
        public string OnClientTargetControlAction
        {
            get { return (ViewState["OnClientTargetControlAction"] == null) ? string.Empty : (string)ViewState["OnClientTargetControlAction"]; }
            set { ViewState["OnClientTargetControlAction"] = value; }
        }

        [DefaultValue(""),
        Category("ClientSide Events"),
        NotifyParentProperty(true),
        RefreshProperties(RefreshProperties.Repaint)]
        public string OnColorPickerMouseout
        {
            get { return (ViewState["OnColorPickerMouseout"] == null) ? string.Empty : (string)ViewState["OnColorPickerMouseout"]; }
            set { ViewState["OnColorPickerMouseout"] = value; }
        }

        [DefaultValue(""),
        Category("ClientSide Events"),
        NotifyParentProperty(true),
        RefreshProperties(RefreshProperties.Repaint)]
        public string OnColorPickerMouseover
        {
            get { return (ViewState["OnColorPickerMouseover"] == null) ? string.Empty : (string)ViewState["OnColorPickerMouseover"]; }
            set { ViewState["OnColorPickerMouseover"] = value; }
        }

        [DefaultValue(""),
        Category("ClientSide Events"),
        NotifyParentProperty(true),
        RefreshProperties(RefreshProperties.Repaint)]
        public string OnColorSelect
        {
            get { return (ViewState["OnColorSelect"] == null) ? string.Empty : (string)ViewState["OnColorSelect"]; }
            set { ViewState["OnColorSelect"] = value; }
        }

        /// <summary>
        /// When true the control will try to resgister the css required by this control.
        /// The default is true. When this control is consumed by the HTML Editor, it's set to
        /// false unless an external stylesheet is referenced by the Embedded instance of this control.
        /// This property is useful for control developers and not for use in user code.
        /// </summary>
        [Browsable(false),
        DefaultValue(true)]
        public virtual bool RegisterCSS
        {
            get
            {
                return (bool)(ViewState["RegisterCSS"] ?? true);
            }
            set
            {
                ViewState["RegisterCSS"] = value;
            }
        }

        [Browsable(false),
        DefaultValue("")]
        public string SelectedColor
        {
            get
            {
                return (string)(ViewState["SelectedColor"] ?? string.Empty);
            }
            set
            {
                ViewState["SelectedColor"] = value;
            }
        }

        [DefaultValue(typeof(Color), ""),
        Description("The shaded shadow cast when showing the editors dialog window"),
        TypeConverter(typeof(WebColorConverter)),
        Category("Appearance"),
        NotifyParentProperty(true),
        RefreshProperties(RefreshProperties.Repaint)]
        public Color ShaderColor
        {
            get { return (ViewState["ShaderColor"] == null) ? Color.Empty : (Color)ViewState["ShaderColor"]; }
            set { ViewState["ShaderColor"] = value; }
        }

        [DefaultValue(20),
        Description("The shaded shadow's opacity cast when showing the editors dialog window"),
        TypeConverter(typeof(WebColorConverter)),
        Category("Appearance"),
        NotifyParentProperty(true),
        RefreshProperties(RefreshProperties.Repaint)]
        public int ShaderOpacity
        {
            get { return (ViewState["ShaderOpacity"] == null) ? 20 : (int)ViewState["ShaderOpacity"]; }
            set { ViewState["ShaderOpacity"] = value; }
        }

        /// <summary>
        /// Control ClientID which will activate and launch the color pick on click (the default, unless TargetControlActivationOn is specified). This can very well be the id of an html element
        /// not necessarily a ServerSide control.
        /// </summary>
        [TypeConverter(typeof(AssociatedHyperLinkConverter)),
        IDReferenceProperty,
        Category("Behavior"),
        Themeable(false),
        DefaultValue(""),
        Description("Target Control"),
        NotifyParentProperty(true),
        RefreshProperties(RefreshProperties.Repaint)]
        public string TargetControl
        {
            get
            {
                return (ViewState["TargetControl"] == null) ? string.Empty : (string)ViewState["TargetControl"];
            }
            set
            {
                this.ViewState["TargetControl"] = value;
            }
        }

        /// <summary>
        /// The event on which the TargetControl gets to activate and launch the ColorPicker. The default is
        /// click.
        /// </summary>
        [DefaultValue(typeof(ClientEventType), "click"),
        NotifyParentProperty(true),
        RefreshProperties(RefreshProperties.Repaint)]
        public ClientEventType TargetControlActivationOn
        {
            get { return (ViewState["TargetControlActivationOn"] == null) ? ClientEventType.click : (ClientEventType)ViewState["TargetControlActivationOn"]; }
            set { (ViewState["TargetControlActivationOn"]) = value; }
        }

        /// <summary>
        /// Only takes effect if target control is not specified and ManuallyInitialize is false. When this
        /// condition is met, by default an image is used to popup the Color Picker
        /// </summary>
        [Editor(typeof(System.Web.UI.Design.ImageUrlEditor), typeof(UITypeEditor)),
        DefaultValue(""),
        NotifyParentProperty(true),
        RefreshProperties(RefreshProperties.Repaint)]
        public string TargetControlImageUrl
        {
            get { return (ViewState["TargetControlImageUrl"] == null) ? string.Empty : (string)ViewState["TargetControlImageUrl"]; }
            set { ViewState["TargetControlImageUrl"] = value; }
        }

        [DefaultValue(""),
        Category("Control will be initialized manually"),
        NotifyParentProperty(true),
        RefreshProperties(RefreshProperties.Repaint)]
        public string UpdatePanelProgressId
        {
            get { return (ViewState["UpdatePanelProgressId"] == null) ? string.Empty : (string)ViewState["UpdatePanelProgressId"]; }
            set { ViewState["UpdatePanelProgressId"] = value; }
        }

        protected virtual string BaseImageSkinFolder
        {
            get
            {
                string url = _baseImageSkinFolder;
                if (IsCustomSkin)
                    url = Helper.GetPhysicalPathByResourceNamespace(url, this);
                return url;
            }
        }

        protected override string ClassName
        {
            get
            {
                string cn = (this.CssClass != string.Empty) ? this.CssClass : this.ClientID;
                return cn + " colorpicker";
            }
        }

        protected override string CssKey
        {
            get
            {
                return _cssKey;
            }
        }

        protected override string KeyFormat
        {
            get
            {
                return _keyFormat;
            }
        }

        protected override bool RenderSharedStyles
        {
            get { return true; }
        }

        protected override bool RenderTreeViewStyles
        {
            get
            {
                return false;
            }
        }

        protected override string RootImageSkinFolder
        {
            get
            {
                string url = _rootImageSkinFolder;
                if (IsCustomSkin)
                    url = Helper.GetPhysicalPathByResourceNamespace(url, this);
                return url;
            }
        }

        protected override string RootSkinFolder
        {
            get
            {
                string url = _rootSkinFolder;
                if (IsCustomSkin)
                    url = Helper.GetPhysicalPathByResourceNamespace(url, this);
                return url;
            }
        }

        protected override string RootTemplateSkinFolder
        {
            get
            {
                string url = _rootTemplateSkinFolder;
                if (IsCustomSkin)
                    url = Helper.GetPhysicalPathByResourceNamespace(url, this);
                return url;
            }
        }

        protected override string StartupCssStyleIdentifier
        {
            get
            {
                return "cp";
            }
        }

        protected override string StyleSheetName
        {
            get
            {
                return _styleSheetName;
            }
        }

        #endregion Properties

        #region Methods

        internal List<CallbackHandler> GetAsyncEvents()
        {
            List<CallbackHandler> handlerList = new List<CallbackHandler>();
            handlerList.Add(new CallbackHandler("colorpicker", "ColorPickerDesignerRequest", ColorPickerDesignerLoadingMessage));
            return handlerList;
        }

        internal virtual void OnColorPickerRequest(EventArgs e)
        {
            string templateName = string.Format(RootTemplateSkinFolder,
            SelectedSkin, "ColorPickerDesigner.html");
            _webResponseData = this.GetTemplateData(templateName).Replace("controlID", ClassName);
        }

        internal virtual void OnColorSelectionChanged(ColorSelectionEventArgs e)
        {
            if (ColorSelectionChanged != null)
            {
                ColorSelectionChanged(this, e);
            }
        }

        internal virtual void RegisterAsyncEvents(ref ScriptControlDescriptor descriptor)
        {
            List<CallbackHandler> handlerList = GetAsyncEvents();
            descriptor.AddScriptProperty("callbacks", ToJsonString(handlerList));
        }

        internal virtual void SetClientSideEventsDescriptor(ref ScriptControlDescriptor descriptor)
        {
            Dictionary<string, string> dic = new Dictionary<string, string>();
            dic.Add("targetControl", OnClientTargetControlAction);
            dic.Add("beginWebRequest", OnClientBeginWebRequest);
            dic.Add("endWebRequest", OnClientEndWebRequest);
            dic.Add("okButton", OnClientOkButton);
            dic.Add("cancelButton", OnClientCancelButton);
            dic.Add("colorMouseOut", OnColorPickerMouseout);
            dic.Add("colorMouseOver", OnColorPickerMouseover);
            dic.Add("colorSelect", OnColorSelect);
            foreach (string eventName in dic.Keys)
            {
                string val = dic[eventName];
                if (!string.IsNullOrEmpty(val))
                    descriptor.AddEvent(eventName, val);
            }
        }

        internal virtual void SetFormElementIdDescriptor(ref ScriptControlDescriptor descriptor)
        {
            descriptor.AddProperty("formElementId", Page.Form.ClientID);
        }

        internal virtual void SetGlobalClassNameDescriptor(ref ScriptControlDescriptor descriptor)
        {
            descriptor.AddProperty("className", ClassName);
        }

        internal virtual void SetPostbackAllFormDataDescriptor(ref  ScriptControlDescriptor descriptor)
        {
            descriptor.AddProperty("postbackAllFormData", PostbackAllFormData);
        }

        internal virtual void SetShaderColorDescriptor(ref ScriptControlDescriptor descriptor)
        {
            if (ShaderColor != Color.Empty)
                descriptor.AddProperty("shaderColor", ColorTranslator.ToHtml(ShaderColor));
        }

        internal virtual void SetShaderOpacityDescriptor(ref ScriptControlDescriptor descriptor)
        {
            descriptor.AddProperty("shaderOpacity", ShaderOpacity);
        }

        internal virtual void SetTargetControlDescriptor(ref  ScriptControlDescriptor descriptor)
        {
            string id = string.Empty;
            if (TargetControl != string.Empty)
                id = TargetControl;
            else if (_popperImage != null)
                id = _popperImage.ClientID;
            if (id != string.Empty)
                descriptor.AddProperty("targetControlId", id);
        }

        internal virtual void SetTargetControlEventNameDescriptor(ref  ScriptControlDescriptor descriptor)
        {
            descriptor.AddProperty("targetControlActivationOn", TargetControlActivationOn.ToString());
        }

        internal virtual void SetUniqueIdDescriptor(ref ScriptControlDescriptor descriptor)
        {
            descriptor.AddProperty("uniqueId", this.UniqueID);
        }

        internal virtual void SetUpdatePanelProgressIdDescriptor(ref ScriptControlDescriptor descriptor)
        {
            string id = string.IsNullOrEmpty(UpdatePanelProgressId) ?
                EmbeddedUpdatePanelProgress.ClientID : UpdatePanelProgressId;
            descriptor.AddProperty("updatePanelProgressId", id);
        }

        protected override void AddAttributesToRender(HtmlTextWriter writer)
        {
            // override to disable
            if (this.ID != null)
                writer.AddAttribute(HtmlTextWriterAttribute.Id, this.ClientID);
            if (this.ClassName != string.Empty)
                writer.AddAttribute("class", ClassName);
            string accessKey = this.AccessKey;
            if (accessKey.Length > 0)
                writer.AddAttribute(HtmlTextWriterAttribute.Accesskey, accessKey);
            if (Display != DisplayMode.NotSet)
                writer.AddStyleAttribute(HtmlTextWriterStyle.Display, Display.ToString());
            if (!this.Enabled)
                writer.AddAttribute(HtmlTextWriterAttribute.Disabled, "disabled");
        }

        protected override void CreateChildControls()
        {
            if (!IsBrowserUpLevel) return;

            if (_cs == null && Page != null)
                _cs = Page.ClientScript;

            ColorPickerPopper();
        }

        protected override IEnumerable<ScriptDescriptor> GetScriptDescriptors()
        {
            ScriptControlDescriptor descriptor = new ScriptControlDescriptor("Typps.ColorPicker", this.ClientID);
            if (DesignMode)
                return new ScriptDescriptor[] { descriptor };
            SetGlobalClassNameDescriptor(ref descriptor);
            SetShaderColorDescriptor(ref descriptor);
            SetShaderOpacityDescriptor(ref descriptor);
            RegisterAsyncEvents(ref descriptor);
            SetClientSideEventsDescriptor(ref descriptor);
            SetTargetControlDescriptor(ref descriptor);
            SetTargetControlEventNameDescriptor(ref descriptor);
            SetUniqueIdDescriptor(ref descriptor);
            SetUpdatePanelProgressIdDescriptor(ref descriptor);
            SetFormElementIdDescriptor(ref descriptor);
            SetPostbackAllFormDataDescriptor(ref descriptor);
            return new ScriptDescriptor[] { descriptor };
        }

        protected override IEnumerable<ScriptReference> GetScriptReferences()
        {
            if (_cs == null) return null;
            ScriptReference reference1 = new ScriptReference();
            bool isDebugMode = SM.ScriptMode == ScriptMode.Debug;
            string script1 = !isDebugMode ? "ClientScripts.startup.min.js" : "ClientScripts.startup.js";
            string script2 = !isDebugMode ? "ClientScripts.modalpopup.min.js" : "ClientScripts.modalpopup.js";
            string script3 = !isDebugMode ? "ClientScripts.colorpicker.min.js" : "ClientScripts.colorpicker.js";
            reference1.Path = _cs.GetWebResourceUrl(typeof(ResourceDummy),
                Helper.GetManifestResourceName(script1,
                ManifestResourceNamesCache, isDebugMode));

            ScriptReference reference2 = new ScriptReference();
            reference2.Path = _cs.GetWebResourceUrl(typeof(ResourceDummy),
                Helper.GetManifestResourceName(script2,
                ManifestResourceNamesCache, isDebugMode));

            ScriptReference reference3 = new ScriptReference();
            reference3.Path = _cs.GetWebResourceUrl(typeof(ColorPicker),
                Helper.GetManifestResourceName(script3,
                ManifestResourceNamesCache, isDebugMode));

            return new ScriptReference[] { reference1, reference2, reference3 };
        }

        protected override void LoadViewState(object state)
        {
            if (state != null)
            {
                object[] states = (object[])state;
                base.LoadViewState(states[0]);
            }
        }

        protected override void OnLoad(EventArgs e)
        {
            /*
                the second request for this page is being made for the css file stream;
                so in case you see onload executing twice, that is because, the second
                request is a request for css file stream! We prefer to go through the
                page life cycle anyway because we also want to collect user specified
                css properties.
             */
            base.OnLoad(e);
            _cs = Page.ClientScript;
            EnsureChildControls();
            if (!this.DesignMode)
            {
                EnsureScriptManager();
                RaiseCallbackEvent();
            }
            string postbackData = ExtractPostbackData();
            if (!string.IsNullOrEmpty(postbackData))
            {
                if (!SelectedColor.Equals(postbackData, StringComparison.OrdinalIgnoreCase))
                {
                    SelectedColor = postbackData;
                    OnColorSelectionChanged(new ColorSelectionEventArgs(postbackData));
                }
            }
        }

        protected override void OnPreRender(EventArgs e)
        {
            base.OnPreRender(e);
            if (DesignMode || IsCallback) return;

            if (SM == null)
                throw new HttpException("A ScriptManager control must exist on the current page.");

            SM.RegisterScriptControl(this);

            if (RegisterCSS)
                base.InitializeCSSRegistration();
        }

        protected override void OnUnload(EventArgs e)
        {
            base.OnUnload(e);
            if (DesignMode) return;
            if (IsCallback)
            {
                if (!string.IsNullOrEmpty(CallbackArgument))
                {
                    ResponseWrite(string.Format("{0}$callbackdata${1}$sep${2}",
                        CallbackArgument, this.ClientID, _webResponseData), "text/plain");
                }
            }
        }

        protected override string QueryStringData(CssFile cssFileToRegister)
        {
            bool formatStyleSheet = SM.ScriptMode == ScriptMode.Debug;
            StringBuilder queryStrings = new StringBuilder(6);
            queryStrings.AppendFormat("&ctl={0}", (int)ControlName.ColorPicker);
            queryStrings.AppendFormat("&s={0}", (int)Skin);
            queryStrings.AppendFormat("&cs={0}", CustomSkin);
            queryStrings.AppendFormat("&csf={0}", CustomSkinFolder);
            queryStrings.AppendFormat("&cc={0}", ClassName);
            queryStrings.AppendFormat("&fcss={0}", formatStyleSheet);
            queryStrings.AppendFormat("&cssfile={0}", cssFileToRegister);

            return queryStrings.ToString();
        }

        protected override void Render(HtmlTextWriter writer)
        {
            if (IsCallback) return;
            if (base.DesignMode)
            {
                this.EnsureChildControls();
            }
            else
            {
                if (SM != null && SM.SupportsPartialRendering)
                    SM.RegisterScriptDescriptors(this);
            }
            base.Render(writer);
        }

        protected override void ResetCollectionsAndStyles()
        {
        }

        protected override object SaveViewState()
        {
            object[] states = new object[1];
            states[0] = base.SaveViewState();
            return states;
        }

        protected override void TrackViewState()
        {
            base.TrackViewState();
        }

        private void ColorPickerPopper()
        {
            if (TargetControl == string.Empty && !ManuallyInitialize)
            {
                _popperImage = new System.Web.UI.WebControls.Image();
                _popperImage.ID = "icon";
                string url = Helper.GetBackgroundImageUrl(this,
                    string.Format(RootImageSkinFolder, SelectedSkin, "colorpicker.gif"));

                if (TargetControlImageUrl != string.Empty)
                    url = ResolveClientUrl(TargetControlImageUrl);

                _popperImage.ImageUrl = url;
                _popperImage.Height = Unit.Parse("14px");
                _popperImage.Width = Unit.Parse("14px");
                _popperImage.Style["cursor"] = "pointer";
                _popperImage.EnableViewState = false;
                this.Controls.Add(_popperImage);
            }
            if (!DesignMode)
            {
                HiddenField hf = new HiddenField();
                hf.ID = "properties";
                hf.Value = string.Empty; // always reset it. we are collecting the value from the forms collection!
                this.Controls.Add(hf);
                if (string.IsNullOrEmpty(UpdatePanelProgressId))
                    CreateUpdatePanelProgress(this);
            }
        }

        void CreateUpdatePanelProgress(Control container)
        {
            EmbeddedUpdatePanelProgress.AttachToUpdatePanelEventHandlers = false;

                if (Skin != SkinNames.Classic && EmbeddedUpdatePanelProgress.Skin == SkinNames.Classic)
                    EmbeddedUpdatePanelProgress.Skin = Skin;

                if (!string.IsNullOrEmpty(CustomSkinFolder) && string.IsNullOrEmpty(EmbeddedUpdatePanelProgress.CustomSkinFolder))
                    EmbeddedUpdatePanelProgress.CustomSkinFolder = CustomSkinFolder;

                if (CustomSkin != "None" && EmbeddedUpdatePanelProgress.CustomSkin == "None")
                    EmbeddedUpdatePanelProgress.CustomSkin = CustomSkin;

                if (!string.IsNullOrEmpty(ExternalStyleSheet) ||
                   !string.IsNullOrEmpty(EmbeddedUpdatePanelProgress.ExternalStyleSheet))
                    EmbeddedUpdatePanelProgress.RegisterCSS = false;

                container.Controls.Add(EmbeddedUpdatePanelProgress);
        }

        private string ExtractPostbackData()
        {
            string key = string.Format("{0}${1}", UniqueID, "properties");
            string value = Context.Request.Form[key];
            if (!string.IsNullOrEmpty(value))
                return value;
            else
                return string.Empty;
        }

        private void RaiseCallbackEvent()
        {
            if (string.IsNullOrEmpty(CallbackArgument))
                return;
            switch (CallbackArgument)
            {
                case "ColorPickerDesignerRequest":
                    OnColorPickerRequest(new EventArgs());
                    break;
            }
        }

        #endregion Methods
    }
}